import json
import logging
import time

from django.shortcuts import render
from django_redis import get_redis_connection
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

from courses.models import Course, CourseExpire

logger = logging.getLogger("django")


# Create your views here.

class CartAPIView(APIView):
    """
    购物车接口:
    必须在登陆的情况下才能访问

    """
    # 设置权限类:只有登陆的用户才能访问
    permission_classes = []

    def post(self, request):
        try:
            logger.info("用户访问添加购物车接口")
            # 1:接受参数
            course_id = request.data.get('course_id')
            user_id = request.user.id
            quantity = request.data.get('quantity', 1)
            logger.info(f"用户{user_id}访问购物车接口,课程ID:{course_id},数量:{quantity}")
            """
            这段代码的功能是：
                检查用户是否已登录，如果未登录则记录错误日志并返回401未授权响应，提示用户未登录。
                具体逻辑：
                    判断request.user.is_authenticated是否为False
                    如果未登录，记录错误日志"用户未登录"
                    返回包含错误码0和提示信息的JSON响应
                    HTTP状态码设置为401（未授权）
            """
            if not request.user.is_authenticated:
                logger.error("用户未登录")
                return Response({
                    "code": 0,
                    "message": "用户未登录",
                }, status=status.HTTP_401_UNAUTHORIZED)

            # 2:验证参数
            if not course_id:
                logger.error("课程ID不能为空")
                return Response({'code': 0, 'message': '课程ID不能为空'})
            # 3:业务逻辑
            # 3.1:查询课程是否存在
            try:
                course = Course.objects.get(id=course_id, is_deleted=False)
                logger.info(f"正在查询的课程是:{course}")
            except Course.DoesNotExist:
                logger.error("课程不存在")
                return Response({'code': 0, 'message': '课程不存在'})

            # 3.2 判断课程是否上架状态
            if course.status != 1:
                logger.error("课程未上架")
                return Response({'code': 0, 'message': '课程未上架'})

            # 3.3 判断课程是否为否免费课程
            if course.course_type == 1:
                logger.info("正在添加的课程是免费课程,免费课程不能添加到购物车")
                return Response({'code': 0, 'message': '免费课程不能添加到购物车'})

            redis_conn = get_redis_connection('cart')
            # redis 购物车的KEY
            cart_key = f"code_env_spaces:carts:cartList:{user_id}"
            # key:课程ID
            course_key = f"course_{course_id}"
            logger.info(f"redis_key:{cart_key},课程ID:{course_key}")

            # 1.1 判断课程是否已经存在到购物车
            if redis_conn.hexists(cart_key, course_key):
                logger.info("课程已经存在购物车中")
                return Response({'code': 0, 'message': '课程已经存在购物车中'})

            course_data = {
                "name": course.name,  # 课程名称
                "image": course.course_img,  # 课程图片
                "is_selected": 1,  # 默认选中
                "price": float(course.price),  # 课程价格
                "quantity": quantity,  # 购买数量
            }
            logger.info(type(course_data))
            course_data_json = json.dumps(course_data)
            logger.info(course_data_json)
            logger.info(type(course_data_json))
            logger.info(f"正在添加的课程是:{course_data}")
            # json.dumps(course_data):将字典(dict)转换为json字符串(str)
            redis_conn.hset(cart_key, course_key, json.dumps(course_data))
            logger.info(f"添加课程成功")
            redis_conn.expire(cart_key, 60 * 60 * 24 * 90)
            logger.info(f"设置过期时间成功")

            order_key = f"code_env_spaces:carts:order:{user_id}"
            redis_conn.zadd(order_key, {course_id: time.time()})
            logger.info(f"设置课程的添加时间🎤")
            redis_conn.expire(order_key, 60 * 60 * 24 * 90)
            logger.info(f"设置课程的添加时间有效期")
            return Response({"code": 1, "message": "添加购物车成功", "data": course_data})
        except Exception as e:
            logger.error(f"添加购物车失败:{str(e)}")
            return Response({"code": 0, "message": f"添加购物车失败:{str(e)}"})


class CartListAPIView(APIView):
    """
    购物车列表接口:
    必须在登陆的情况下才能访问
    """

    permission_classes = []

    def get(self, request):
        logger.info("进入购物车列表接口")
        try:
            if not request.user.is_authenticated:
                logger.error("用户未登录")
                return Response({
                    "code": 0,
                    "message": "用户未登录",
                }, status=status.HTTP_401_UNAUTHORIZED)

            user_id = request.user.id
            redis_conn = get_redis_connection('cart')
            # redis 购物车的KEY
            cart_key = f"code_env_spaces:carts:cartList:{user_id}"
            cart_data = redis_conn.hgetall(cart_key)
            if not cart_data:
                logger.info("购物车为空")
                return Response({"code": 0, "message": "购物车为空"})
            order_key = f"code_env_spaces:carts:order:{user_id}"
            # 获取课程的添加时间
            courses_times = redis_conn.zrange(order_key, 0, -1, withscores=True)
            # [(b'3', 1754529320.068316), (b'4', 1754529326.651274), (b'1', 1754529332.318923)]
            logger.info(f"课程的添加时间:{courses_times}")

            courses_time_dict = {}
            for redis_course_id_btyes, redis_course_time in courses_times:
                redis_course_id = redis_course_id_btyes.decode('utf-8')
                logger.info(f"课程ID:{redis_course_id},课程添加时间:{redis_course_time}")
                courses_time_dict[redis_course_id] = redis_course_time

            logger.info(f"从redis里面获取到添加时间:{courses_time_dict}")
            logger.info(f"购物车数据:{cart_data}")
            # 购物车数据类型:<class 'dict'>
            logger.info(f"购物车数据类型:{type(cart_data)}")
            cart_list = []
            for course_id, course_info in cart_data.items():
                logger.info(f"课程ID:{course_id},课程信息:{course_info}")
                # 课程ID类型:<class 'bytes'>,课程信息类型:<class 'bytes'>
                logger.info(f"课程ID类型:{type(course_id)},课程信息类型:{type(course_info)}")
                # bytes 类型转换为str类型:将 course_id 这个 bytes 对象转换为 utf-8 编码的字符串。
                course_id_str = course_id.decode('utf-8')
                logger.info(f"课程ID:{course_id_str}")
                logger.info(f"课程ID类型:{type(course_id_str)}")

                course_info_str = course_info.decode('utf-8')
                logger.info(f"课程信息:{course_info_str}")
                logger.info(f"课程信息类型:{type(course_info_str)}")

                # json.loads() 方法:讲字符串转化成字典。
                course_info_dict = json.loads(course_info_str)

                course = Course.objects.get(id=course_id_str.split('_')[-1])

                add_time = courses_time_dict.get(course_id_str.split('_')[-1], 0)

                logger.info(f"课程添加时间:{add_time}")

                my_course_info = {
                    'id': course_id_str.split('_')[-1],
                    'name': course_info_dict['name'],
                    'course_img': course_info_dict['image'],
                    'price': course.price,  # 最新的课程价格
                    'is_selected': course_info_dict['is_selected']
                }

                # [({'id': '3', 'name': '大数据从入门到放弃', 'course_img': 'http://img3x6.ddimg.cn/28/3/11383904296-1_h_1707123040.jpg', 'price': Decimal('0.10'), 'is_selected': 1}, 1754529320.068316), ({'id': '4', 'name': 'Python大模型', 'course_img': 'http://img3x7.ddimg.cn/20/6/1291990907-1_h_245.jpg', 'price': Decimal('11.00'), 'is_selected': 1}, 1754529326.651274), ({'id': '1', 'name': 'python从入门到放弃', 'course_img': 'http://img62.ddimg.cn/upload_img/00802/1/B1-8064-1620716364.jpg', 'price': Decimal('9.90'), 'is_selected': 1}, 1754529332.318923)]]
                cart_list.append((my_course_info, add_time))
                logger.info(f"cart_list-------:{cart_list}")
            # 按添加时间倒序排列（最新的在前）
            cart_list.sort(key=lambda x: x[1], reverse=True)
            # [排序后的cart_list-------:[({'id': '1', 'name': 'python从入门到放弃', 'course_img': 'http://img62.ddimg.cn/upload_img/00802/1/B1-8064-1620716364.jpg', 'price': Decimal('9.90'), 'is_selected': 1}, 1754529332.318923), ({'id': '4', 'name': 'Python大模型', 'course_img': 'http://img3x7.ddimg.cn/20/6/1291990907-1_h_245.jpg', 'price': Decimal('11.00'), 'is_selected': 1}, 1754529326.651274), ({'id': '3', 'name': '大数据从入门到放弃', 'course_img': 'http://img3x6.ddimg.cn/28/3/11383904296-1_h_1707123040.jpg', 'price': Decimal('0.10'), 'is_selected': 1}, 1754529320.068316)]]
            logger.info(f"排序后的cart_list-------:{cart_list}")
            # 提取排序后的课程信息列表
            sort_cart_list = [item[0] for item in cart_list]
            return Response({
                "code": 1,
                "message": "获取购物车数据成功",
                "data":{
                    "cart_list":sort_cart_list
                }
            }, status=status.HTTP_200_OK)

        except Exception as e:
            logger.error(e)
            return Response({
                "code": 0,
                "message": "获取购物车数据失败"
            })


class CartDelAPIView(APIView):
    """
    删除购物车数据

    单删:
    {
    "course_ids":1
    }
    批量删除:
     {
    "course_ids":[1,2,3]
    }
    """
    permission_classes = []

    def post(self, request):
        if not request.user.is_authenticated:
            logger.error("用户未登录")
            return Response({
                "code": 0,
                "message": "用户未登录",
            }, status=status.HTTP_401_UNAUTHORIZED)

        user_id = request.user.id

        course_ids = request.data.get("course_ids")
        if not course_ids:
            logger.error("参数错误")
            return Response({
                "code": 0,
                "message": "    请选择要删除的课程",
            })

        try:
            if isinstance(course_ids, int):
                # 单删
                course_ids = [course_ids]
            elif not isinstance(course_ids, list):
                # 批量删除
                return Response({
                    "code": 0,
                    "message": "参数格式错误",
                })

            redis_conn = get_redis_connection('cart')
            cart_key = f"code_env_spaces:carts:cartList:{user_id}"

            deled_count = 0
            for course_id in course_ids:
                # key:课程ID
                course_key = f"course_{course_id}"
                if redis_conn.hexists(cart_key, course_key):
                    # 删除课程
                    redis_conn.hdel(cart_key, course_key)
                    deled_count += 1

            logger.info(f"删除购物车数据成功,一共删除了{deled_count}条数据")
            return Response({
                "code": 1,
                "message": "删除购物车数据成功",
                "data": {
                    "deleted_count": deled_count
                }
            })

        except Exception as e:
            logger.error(e)
            return Response({
                "code": 0,
                "message": "删除购物车数据失败",
            })


class CartSelectAllView(APIView):
    """
    全选/取消全选;
     1(全选) 0(取消全选)
    """

    def post(self, request):
        if not request.user.is_authenticated:
            logger.error("用户未登录")
            return Response({
                "code": 0,
                "message": "用户未登录",
            }, status=status.HTTP_401_UNAUTHORIZED)

        user_id = request.user.id

        # 1,0
        selected = request.data.get("selected")
        logger.info(f"用户{user_id}选择🉐️状态{selected}")

        if selected is None:
            logger.error("参数错误")
            return Response({
                "code": 0,
                "message": "请选择要选中的状态",
            })
        if selected not in (0, 1):
            logger.error("参数错误")
            return Response({
                "code": 0,
                "message": "选择的状态必须是0或者1",
            })

        try:
            redis_conn = get_redis_connection('cart')
            cart_key = f"code_env_spaces:carts:cartList:{user_id}"
            cart_data = redis_conn.hgetall(cart_key)
            if not cart_data:
                logger.error("购物车为空")
                return Response({
                    "code": 0,
                    "message": "购物车为空",
                })

            logger.info(f"购物车数据:{cart_data}")
            updated_count = 0
            for course_key, course_data_bytes in cart_data.items():
                logger.info(f"课程id:{course_key},课程数据:{course_data_bytes}")
                course_data = json.loads(course_data_bytes.decode("utf-8"))
                if course_data["is_selected"] != selected:
                    course_data["is_selected"] = selected
                    redis_conn.hset(cart_key, course_key, json.dumps(course_data))
                    updated_count += 1

            action = "全选" if selected else "取消全选"
            return Response({
                "code": 1,
                "message": f"{action}操作成功",
                "data":
                    {
                        "updated_count": updated_count
                    }
            })
        except Exception as e:
            logger.error(e)
            return Response({
                "code": 0,
                "message": f"{action}操作成功",
            })


class CartToggleView(APIView):
    """
    反选:
    课程ID
    批量反选. 单个反选
    状态取反
    """

    def post(self,request):
        if not request.user.is_authenticated:
            logger.error("用户未登录")
            return Response({
                "code": 0,
                "message": "用户未登录",
            }, status=status.HTTP_401_UNAUTHORIZED)

        user_id = request.user.id

        course_ids = request.data.get("course_ids")
        if not course_ids:
            return Response({
                "code": 0,
                "message": "请选择他要切换的课程",
            })

        try:
            if isinstance(course_ids, int):
                # 单个反选
                course_ids = [course_ids]
            elif not isinstance(course_ids, list):
                # 批量反选
                return Response({
                    "code": 0,
                    "message": "参数格式错误",
                })
            redis_conn = get_redis_connection('cart')
            cart_key = f"code_env_spaces:carts:cartList:{user_id}"
            cart_data = redis_conn.hgetall(cart_key)
            if not cart_data:
                logger.error("购物车为空")
                return Response({
                    "code": 0,
                    "message": "购物车为空",
                })

            logger.info(f"购物车数据:{cart_data}")
            updated_count=0
            updated_course=[]
            for course_id in course_ids:
                # key:课程ID
                course_key = f"course_{course_id}"
                if redis_conn.hexists(cart_key,course_key):
                    course_data = json.loads(redis_conn.hget(cart_key,course_key))
                    logger.info(f"课程xinxi数据:{course_data}")
                    course_data["is_selected"] = 1 if course_data["is_selected"]==0 else 0
                    redis_conn.hset(cart_key,course_key,json.dumps(course_data))
                    updated_count+=1
                    updated_course.append({
                        "course_id":course_id,
                        "is_selected":course_data["is_selected"]
                    })
            return Response({
                "code": 1,
                "message": "成功",
                "data":{
                    "updated_count":updated_count,
                    "updated_course":updated_course
                }

            })
        except Exception as e:
            logger.error(e)
            return Response({
                "code": 0,
                "message": "失败"
            }, status=500)

